package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/ammyhaber/seckill/pkg/breaker"
	"github.com/ammyhaber/seckill/pkg/config"
	"github.com/ammyhaber/seckill/pkg/httpclient"
	"github.com/ammyhaber/seckill/pkg/limiter"
	"github.com/ammyhaber/seckill/pkg/metrics"
	"github.com/ammyhaber/seckill/pkg/mq"
	"github.com/ammyhaber/seckill/service/order/dao"
	"github.com/ammyhaber/seckill/service/order/middleware"
	"github.com/ammyhaber/seckill/service/order/service"
	"github.com/go-redis/redis/v8"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

func main() {
	// 创建上下文
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 初始化数据库连接
	db, err := initDB()
	if err != nil {
		log.Fatalf("初始化数据库失败: %v\n", err)
	}
	defer db.Close()

	// 初始化Redis连接
	redisClient := initRedis()
	defer redisClient.Close()

	// 测试Redis连接
	if err := redisClient.Ping(ctx).Err(); err != nil {
		log.Fatalf("连接Redis失败: %v", err)
	}

	// 初始化动态配置中心
	dynamicConfig := config.NewDynamicConfig(redisClient)
	dynamicConfig.Start(ctx)
	defer dynamicConfig.Stop()

	// 初始化指标收集器
	metricsCollector := metrics.NewMetricsCollector(redisClient, "seckill:metrics", 10*time.Second)
	metricsCollector.Start(ctx)
	defer metricsCollector.Stop()

	// 初始化RabbitMQ
	orderMQ, err := mq.NewOrderMQ()
	if err != nil {
		log.Fatalf("初始化RabbitMQ失败: %v\n", err)
	}
	defer orderMQ.Close()

	// 初始化队列
	if err := orderMQ.InitOrderQueue(); err != nil {
		log.Fatalf("初始化订单队列失败: %v\n", err)
	}

	// 初始化各层组件
	orderDAO := dao.NewOrderDAO(db)
	inventoryAPI := "http://localhost:8080" // 库存服务API地址，实际应从配置文件读取
	orderService := service.NewOrderService(orderDAO, redisClient, orderMQ, inventoryAPI)
	// orderAPI := api.NewOrderAPI(orderService) // 未使用，暂时注释掉

	// 设置HTTP客户端
	inventoryClient := httpclient.NewHttpClient(inventoryAPI, 5*time.Second, 3)
	orderService.SetHTTPClient(inventoryClient)

	// 从配置获取限流参数
	globalLimit := dynamicConfig.GetInt("limiter.global.rate", 100)
	globalBurst := dynamicConfig.GetInt("limiter.global.burst", 200)

	// 创建全局限流器
	globalLimiter := limiter.NewTokenBucket(float64(globalLimit), globalBurst)

	// 记录全局限流器指标
	globalLimiterMetrics := metrics.NewLimiterMetrics(metricsCollector, "global")

	// 创建分布式用户限流器
	userLimiter := limiter.NewUserRateLimiter(
		redisClient,
		dynamicConfig.GetInt("limiter.user.rate", 10),
		dynamicConfig.GetDuration("limiter.user.period", 1*time.Minute),
	)

	// 创建分布式IP限流器
	ipLimiter := limiter.NewIPRateLimiter(
		redisClient,
		dynamicConfig.GetInt("limiter.ip.rate", 20),
		dynamicConfig.GetDuration("limiter.ip.period", 1*time.Minute),
	)

	// 路径级别限流器配置
	pathLimitConfigs := []struct {
		path  string
		rate  string
		burst string
	}{
		{"/order/create", "limiter.path.create.rate", "limiter.path.create.burst"},
		{"/order/pay", "limiter.path.pay.rate", "limiter.path.pay.burst"},
		{"/order/cancel", "limiter.path.cancel.rate", "limiter.path.cancel.burst"},
		{"/order/detail", "limiter.path.detail.rate", "limiter.path.detail.burst"},
		{"/order/list", "limiter.path.list.rate", "limiter.path.list.burst"},
	}

	// 创建路径级别限流器
	pathLimiters := make(map[string]limiter.RateLimiter)
	for _, config := range pathLimitConfigs {
		rate := dynamicConfig.GetInt(config.rate, 20)
		burst := dynamicConfig.GetInt(config.burst, 50)
		pathLimiters[config.path] = limiter.NewTokenBucket(float64(rate), burst)
	}

	// 创建适应性熔断器
	adaptiveBreaker := breaker.NewAdaptiveBreaker(
		breaker.WithErrorThreshold(dynamicConfig.GetFloat("breaker.error_threshold", 0.5)),
		breaker.WithMinRequestCount(dynamicConfig.GetInt("breaker.request_volume", 20)),
		breaker.WithRecoveryWindow(dynamicConfig.GetDuration("breaker.recovery_window", 30*time.Second)),
		breaker.WithRecoveryRate(dynamicConfig.GetFloat("breaker.recovery_rate", 0.1)),
	)

	// 记录熔断器指标
	breakerMetrics := metrics.NewBreakerMetrics(metricsCollector, "adaptive")

	// 配置熔断器降级函数
	adaptiveBreaker.RegisterFallback("orderCreate", func(err error) (interface{}, error) {
		// 记录降级指标
		breakerMetrics.RecordRejected()

		// 返回降级响应
		return nil, err
	})

	// 注册熔断器状态变更监听
	dynamicConfig.AddListener("breaker.error_threshold", func(key string, oldValue, newValue interface{}) {
		if _, ok := newValue.(float64); ok {
			adaptiveBreaker.Reset() // 重置后应用新配置
		}
	})

	// 获取全局熔断器管理器包装器并注册自适应熔断器
	breakerManagerWrapper := middleware.GetBreakerManagerWrapper()
	breakerManagerWrapper.RegisterAdaptiveBreaker("orderService", adaptiveBreaker)

	// 创建路由器
	router := http.NewServeMux()

	// 初始化路由

	// TODO: 添加路由处理器
	// 例如：router.HandleFunc("/order/create", orderAPI.CreateOrderHandler)

	// 应用中间件
	var handler http.Handler = router

	// 添加用户和IP限流中间件
	handler = middleware.UserIPLimiterMiddleware(userLimiter, ipLimiter)(handler)

	// 应用全局限流和指标收集
	handler = middleware.MetricsLimiterMiddleware(globalLimiter, globalLimiterMetrics)(handler)

	// 应用路径限流
	handler = middleware.PathRateLimiterMiddleware(pathLimiters)(handler)

	// 应用自适应熔断
	handler = middleware.AdaptiveBreakerMiddleware(adaptiveBreaker, "orderService", breakerMetrics)(handler)

	// 创建流量削峰器并注册消息处理器
	peakShaver := mq.NewPeakShaver(orderMQ, 20, 50.0) // 20个工作协程，每秒处理50个消息

	// 注册订单消息处理
	peakShaver.RegisterHandler("orderCreate", func(data []byte) error {
		return orderService.HandleDelayMessage(ctx, data)
	})

	// 启动流量削峰服务
	if err := peakShaver.Start(); err != nil {
		log.Printf("启动流量削峰服务失败: %v\n", err)
	}
	defer peakShaver.Stop()

	// 创建定时任务，处理过期订单
	go func() {
		ticker := time.NewTicker(1 * time.Minute)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				if err := orderService.HandleExpiredOrders(ctx); err != nil {
					log.Printf("处理过期订单失败: %v", err)
				}
			case <-ctx.Done():
				return
			}
		}
	}()

	// 启动HTTP服务
	server := &http.Server{
		Addr:         ":8081", // 订单服务端口，与库存服务区分
		Handler:      handler, // 使用应用了中间件的handler
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  15 * time.Second,
	}

	// 优雅关闭
	go func() {
		log.Println("订单服务启动，监听端口: 8081")
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("HTTP服务启动失败: %v\n", err)
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt)
	<-quit

	// 收到中断信号，优雅关闭服务器
	log.Println("正在关闭服务器...")

	// 创建关闭上下文，超时10秒
	ctxShutdown, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := server.Shutdown(ctxShutdown); err != nil {
		log.Fatalf("服务器关闭失败: %v", err)
	}

	log.Println("服务器已关闭")
}

// initDB 初始化数据库连接
func initDB() (*sqlx.DB, error) {
	// 数据库连接信息，实际应从配置文件读取
	dsn := "user:password@tcp(mysql:3306)/seckill?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := sqlx.Connect("mysql", dsn)
	if err != nil {
		return nil, err
	}

	// 设置连接池参数
	db.SetMaxOpenConns(100)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(time.Hour)

	return db, nil
}

// initRedis 初始化Redis连接
func initRedis() *redis.Client {
	// Redis连接信息，实际应从配置文件读取
	return redis.NewClient(&redis.Options{
		Addr:     "redis:6379",
		Password: "",
		DB:       0,
		PoolSize: 100,
	})
}
